package com.dotndot.view.activity;

import java.io.UnsupportedEncodingException;
import java.text.SimpleDateFormat;
import java.util.Date;

import android.app.DatePickerDialog;
import android.os.Bundle;
import android.os.Message;
import android.text.Editable;
import android.text.InputFilter;
import android.text.Spanned;
import android.text.TextWatcher;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.DatePicker;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RadioGroup;
import android.widget.RadioGroup.OnCheckedChangeListener;
import android.widget.Toast;

import com.dotndot.MomApplication;
import com.dotndot.R;
import com.dotndot.controller.Server.ReceiveServerParam;
import com.dotndot.controller.Server.SendServerParam;
import com.dotndot.controller.network.resData.ResGson;
import com.dotndot.controller.network.resData.Response;
import com.dotndot.view.widget.BaseDialog;

public class Join extends BaseActivity
{

    private enum VIEW_TYPE
    {
        EMAIL_AND_PASSWORD_VIEW, USER_INFO_VIEW,
    }

    private EditText mEmail, mPw, mConfirmPw, mNickName, mBirthDay;
    private String mGender = "female";
    private RadioGroup mRadioGroup = null;
    private Button backBtn = null, nextBtn = null;
    private LinearLayout emailAndPasswordLayout = null;
    private LinearLayout userInfoLayout = null;
    private boolean emailInput = false, pwInput = false, confirmPwInput = false;
    private boolean nickNameInput = false, birthDayInput = false;
    private VIEW_TYPE viewType = VIEW_TYPE.EMAIL_AND_PASSWORD_VIEW;
    private Date mDate = null;
    private ImageView mTopIcon1 = null, mTopIcon2 = null, mTopIcon3 = null;
    
    
    @Override
    protected void onCreate( Bundle savedInstanceState )
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.join);

        viewInit();
    }

    @Override
    public void viewInit()
    {
        mDate = new Date();
        mEmail = (EditText) findViewById(R.id.email);
        mPw = (EditText) findViewById(R.id.pw);
        mConfirmPw = (EditText) findViewById(R.id.confirm_pw);
        mNickName = (EditText) findViewById(R.id.nickname);
        InputFilter[] filters = new InputFilter[] {new ByteLengthFilter(MomApplication.MAX_NICKNAME_LENGTH, "KSC5601")};
        mNickName.setFilters(filters);
        mBirthDay = (EditText) findViewById(R.id.birthday);
        mRadioGroup = (RadioGroup) findViewById(R.id.gender);

        backBtn = (Button) findViewById(R.id.back);
        nextBtn = (Button) findViewById(R.id.next);

        mTopIcon1 = (ImageView) findViewById(R.id.top_icon1);
        mTopIcon2 = (ImageView) findViewById(R.id.top_icon2);
        mTopIcon3 = (ImageView) findViewById(R.id.top_icon3);
        
        emailAndPasswordLayout = (LinearLayout) findViewById(R.id.emailAndpassword);
        userInfoLayout = (LinearLayout) findViewById(R.id.userInfo);

        setViewType(viewType);
    }

    private void setViewType( VIEW_TYPE type )
    {
        switch( type )
        {
            case EMAIL_AND_PASSWORD_VIEW:
                setEmailAndPasswordView();
                break;

            case USER_INFO_VIEW:
                setUserInfoView();
                break;
        }
    }

    private void setEmailAndPasswordView()
    {
        mTopIcon1.setVisibility(View.INVISIBLE);
        mTopIcon2.setVisibility(View.VISIBLE);
        mTopIcon3.setVisibility(View.INVISIBLE);
        
        mEmail.addTextChangedListener(emailWatcher);
        mPw.addTextChangedListener(pwWatcher);
        mConfirmPw.addTextChangedListener(confirmPwWatcher);

        backBtn.setText(R.string.back);
        backBtn.setVisibility(View.VISIBLE);
        backBtn.setOnClickListener(new OnClickListener()
        {
            @Override
            public void onClick( View v )
            {
                utilAPI.callActivity(Join.this, Login.class);
                finish();
            }
        });
        nextBtn.setText(R.string.next);
        nextBtn.setVisibility(View.VISIBLE);
        checkNextButton();
        nextBtn.setOnClickListener(new OnClickListener()
        {
            @Override
            public void onClick( View v )
            {
                if( checkEmailAndPasswordData() )
                {
                    viewType = VIEW_TYPE.USER_INFO_VIEW;
                    setViewType(viewType);
                }
            }
        });

        emailAndPasswordLayout.setVisibility(View.VISIBLE);
        userInfoLayout.setVisibility(View.GONE);
    }

    private void setUserInfoView()
    {
        mTopIcon1.setVisibility(View.INVISIBLE);
        mTopIcon2.setVisibility(View.INVISIBLE);
        mTopIcon3.setVisibility(View.VISIBLE);
        
        mNickName.addTextChangedListener(nickNameWatcher);
        mRadioGroup.setOnCheckedChangeListener(new OnCheckedChangeListener()
        {
            @Override
            public void onCheckedChanged( RadioGroup group, int checkedId )
            {
                switch( checkedId )
                {
                    case R.id.female:
                        mGender = "female";
                        break;

                    case R.id.male:
                        mGender = "male";
                        break;
                }

            }
        });

        mBirthDay.addTextChangedListener(birthdayWatcher);
        mBirthDay.setOnClickListener(new OnClickListener()
        {
            @Override
            public void onClick( View v )
            {
                new DatePickerDialog(Join.this, dateListener, mDate.getYear() + 1900, mDate.getMonth(), mDate.getDate()).show();
            }
        });

        backBtn.setText(R.string.back);
        backBtn.setVisibility(View.VISIBLE);
        backBtn.setOnClickListener(new OnClickListener()
        {
            @Override
            public void onClick( View v )
            {
                viewType = VIEW_TYPE.EMAIL_AND_PASSWORD_VIEW;
                setViewType(viewType);
            }
        });
        nextBtn.setText(R.string.join);
        nextBtn.setVisibility(View.VISIBLE);
        checkNextButton();
        nextBtn.setOnClickListener(new OnClickListener()
        {
            @Override
            public void onClick( View v )
            {
                SendServerParam param = new SendServerParam(REQUEST.JOIN_API);
                param.put(JOIN.email, mEmail.getText().toString());
                param.put(JOIN.password, mPw.getText().toString());
                param.put(JOIN.gender, mGender);
                param.put(JOIN.nickname, mNickName.getText().toString());
                param.put(JOIN.birthday, mBirthDay.getText().toString());
                param.put(JOIN.terms, "true");
                requestNetwork(param);
            }
        });
        emailAndPasswordLayout.setVisibility(View.GONE);
        userInfoLayout.setVisibility(View.VISIBLE);
    }

    DatePickerDialog.OnDateSetListener dateListener = new DatePickerDialog.OnDateSetListener()
    {
        @Override
        public void onDateSet( DatePicker view, int year, int monthOfYear, int dayOfMonth )
        {
            mDate.setYear(year - 1900);
            mDate.setMonth(monthOfYear);
            mDate.setDate(dayOfMonth);

            SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
            String dateText = format.format(mDate);
            mBirthDay.setText(dateText);
        }
    };

    private void checkNextButton()
    {
        if( viewType == VIEW_TYPE.EMAIL_AND_PASSWORD_VIEW )
        {
            if( emailInput && pwInput && confirmPwInput )
            {
                nextBtn.setEnabled(true);
            }
            else
            {
                nextBtn.setEnabled(false);
            }
        }
        else if( viewType == VIEW_TYPE.USER_INFO_VIEW )
        {
            if( nickNameInput && birthDayInput )
            {
                nextBtn.setEnabled(true);
            }
            else
            {
                nextBtn.setEnabled(false);
            }
        }
    }

    private TextWatcher emailWatcher = new TextWatcher()
    {
        @Override
        public void onTextChanged( CharSequence s, int start, int before, int count )
        {
            if( s.length() > 0 )
            {
                emailInput = true;
            }
            else
            {
                emailInput = false;
            }
            checkNextButton();
        }

        @Override
        public void beforeTextChanged( CharSequence s, int start, int count, int after )
        {
        }

        @Override
        public void afterTextChanged( Editable s )
        {
        }
    };

    private TextWatcher pwWatcher = new TextWatcher()
    {
        @Override
        public void onTextChanged( CharSequence s, int start, int before, int count )
        {
            if( s.length() >= MomApplication.MIN_PW_LENGTH )
            {
                pwInput = true;
            }
            else
            {
                pwInput = false;
            }
            checkNextButton();
        }

        @Override
        public void beforeTextChanged( CharSequence s, int start, int count, int after )
        {
        }

        @Override
        public void afterTextChanged( Editable s )
        {
        }
    };

    private TextWatcher confirmPwWatcher = new TextWatcher()
    {
        @Override
        public void onTextChanged( CharSequence s, int start, int before, int count )
        {
            if( s.length() >= MomApplication.MIN_PW_LENGTH )
            {
                confirmPwInput = true;
            }
            else
            {
                confirmPwInput = false;
            }
            checkNextButton();
        }

        @Override
        public void beforeTextChanged( CharSequence s, int start, int count, int after )
        {
        }

        @Override
        public void afterTextChanged( Editable s )
        {
        }
    };

    private TextWatcher nickNameWatcher = new TextWatcher()
    {
        @Override
        public void onTextChanged( CharSequence s, int start, int before, int count )
        {
            if( s.length() > 0 )
            {
                nickNameInput = true;
            }
            else
            {
                nickNameInput = false;
            }
            checkNextButton();
        }

        @Override
        public void beforeTextChanged( CharSequence s, int start, int count, int after )
        {
        }

        @Override
        public void afterTextChanged( Editable s )
        {
        }
    };

    private TextWatcher birthdayWatcher = new TextWatcher()
    {
        @Override
        public void onTextChanged( CharSequence s, int start, int before, int count )
        {
            if( s.length() > 0 )
            {
                birthDayInput = true;
            }
            else
            {
                birthDayInput = false;
            }
            checkNextButton();
        }

        @Override
        public void beforeTextChanged( CharSequence s, int start, int count, int after )
        {
        }

        @Override
        public void afterTextChanged( Editable s )
        {
        }
    };

    private boolean checkEmailAndPasswordData()
    {
        String email = mEmail.getText().toString();
        String pw = mPw.getText().toString();
        String confirm_pw = mConfirmPw.getText().toString();

        if( utilAPI.isEmailValidate(email) == false )
        {
            BaseDialog.getIns().showDialog(Join.this, R.string.invalid_email);
            return false;
        }

        if( utilAPI.validLengthPW(pw) == false )
        {
            BaseDialog.getIns().showDialog(Join.this, R.string.invalid_short_password);
            return false;
        }

        if( pw.equals(confirm_pw) == false )
        {
            BaseDialog.getIns().showDialog(Join.this, R.string.invalid_unequal_password);
            return false;
        }

        if( utilAPI.haveBlank(pw) == true )
        {
            BaseDialog.getIns().showDialog(Join.this, R.string.invalid_have_blank_password);
            return false;
        }

        if( utilAPI.isLowercaseAndNumeric(pw) == false )
        {
            BaseDialog.getIns().showDialog(Join.this, R.string.invalid_type_password);
            return false;
        }

        return true;
    }

    @Override
    public void receiveServerMsg( Message msg )
    {
        ReceiveServerParam recvData = (ReceiveServerParam) msg.obj;

        switch( recvData.getAPI() )
        {
            case JOIN_API:
                String resJson = (String) recvData.getData();
                ResGson resGson = new ResGson(resJson);

                if( resGson.status.equals(Response.Status.OK.name()) )
                {
                    Toast.makeText(Join.this, R.string.join_success, Toast.LENGTH_LONG).show();
                    utilAPI.callActivity(this, Login.class);
                    finish();
                }
                else
                {
                    if( resGson.code.equals(Response.Code.W001.name()) )
                    {
                        BaseDialog.getIns().showDialog(Join.this, R.string.invalid_email);
                    }
                    else if( resGson.code.equals(Response.Code.W002.name()) )
                    {
                        BaseDialog.getIns().showDialog(Join.this, R.string.invalid_password);
                    }
                    else if( resGson.code.equals(Response.Code.E003.name()) )
                    {
                        BaseDialog.getIns().showDialog(Join.this, R.string.join_duplicated_email);
                    }
                    else
                    {
                        BaseDialog.getIns().showDialog(Join.this, R.string.network_unknown_error);
                    }
                }
                break;
        }
    }

    @Override
    public void onClick( View arg0 )
    {
        // TODO Auto-generated method stub

    }

    
    
    
    /**
     * EditText 등의 필드에 텍스트 입력/수정시 
     * 입력문자열의 바이트 길이를 체크하여 입력을 제한하는 필터.
     *
     */
    public class ByteLengthFilter implements InputFilter {


        private String mCharset; //인코딩 문자셋

        protected int mMaxByte; // 입력가능한 최대 바이트 길이

        public ByteLengthFilter(int maxbyte, String charset) {
            this.mMaxByte = maxbyte;
            this.mCharset = charset;
        }

        /**
         * 이 메소드는 입력/삭제 및 붙여넣기/잘라내기할 때마다 실행된다.
         *
         * - source : 새로 입력/붙여넣기 되는 문자열(삭제/잘라내기 시에는 "")
         * - dest : 변경 전 원래 문자열
         */
        public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart,
                int dend) {

            // 변경 후 예상되는 문자열
            String expected = new String();
            expected += dest.subSequence(0, dstart);
            expected += source.subSequence(start, end);
            expected += dest.subSequence(dend, dest.length());

            int keep = calculateMaxLength(expected) - (dest.length() - (dend - dstart));

            if (keep <= 0) {
                return ""; // source 입력 불가(원래 문자열 변경 없음)
            } else if (keep >= end - start) {
                return null; // keep original. source 그대로 허용
            } else {
                return source.subSequence(start, start + keep); // source중 일부만 입력 허용
            }
        }

        /**
         * 입력가능한 최대 문자 길이(최대 바이트 길이와 다름!).
         */
        protected int calculateMaxLength(String expected) {
            return mMaxByte - (getByteLength(expected) - expected.length());
        }    
        
        /**
         * 문자열의 바이트 길이.
         * 인코딩 문자셋에 따라 바이트 길이 달라짐.
         * @param str
         * @return
         */
        private int getByteLength(String str) {
            try {
                return str.getBytes(mCharset).length;
            } catch (UnsupportedEncodingException e) {
                //e.printStackTrace();
            }
            return 0;
        }
    }        
}
